{{>licenseInfo}}
/* tslint:disable:no-unused-variable member-ordering */

import { Inject, Injectable, Optional }                      from '@angular/core';
{{#useHttpClient}}
import { HttpClient, HttpHeaders, HttpParams,
         HttpResponse, HttpEvent, HttpParameterCodec }       from '@angular/common/http';
import { CustomHttpParameterCodec }                          from '../encoder';
{{/useHttpClient}}
{{^useHttpClient}}
import { Http, Headers, URLSearchParams,
        RequestMethod, RequestOptions, RequestOptionsArgs,
        Response, ResponseContentType, QueryEncoder }        from '@angular/http';
import { CustomQueryEncoderHelper }                          from '../encoder';
{{/useHttpClient}}
{{^useRxJS6}}
import { Observable }                                        from 'rxjs/Observable';
{{/useRxJS6}}
{{#useRxJS6}}
import { Observable }                                        from 'rxjs';
{{/useRxJS6}}
{{^useHttpClient}}
import '../rxjs-operators';
{{/useHttpClient}}

{{#imports}}
import { {{classname}} } from '../model/models';
{{/imports}}

import { BASE_PATH, COLLECTION_FORMATS }                     from '../variables';
import { Configuration }                                     from '../configuration';
{{#withInterfaces}}
import {
    {{classname}}Interface{{#useSingleRequestParameter}}{{#operations}}{{#operation}}{{#allParams.0}},
    {{#prefixParameterInterfaces}}{{classname}}{{/prefixParameterInterfaces}}{{operationIdCamelCase}}RequestParams{{/allParams.0}}{{/operation}}{{/operations}}{{/useSingleRequestParameter}}
} from './{{classFilename}}Interface';
{{/withInterfaces}}

{{#operations}}

{{^withInterfaces}}
{{#useSingleRequestParameter}}
{{#operation}}
{{#allParams.0}}
export interface {{#prefixParameterInterfaces}}{{classname}}{{/prefixParameterInterfaces}}{{operationIdCamelCase}}RequestParams {
{{#allParams}}
    {{paramName}}{{^required}}?{{/required}}: {{{dataType}}}{{#isNullable}} | null{{/isNullable}};
{{/allParams}}
}

{{/allParams.0}}
{{/operation}}
{{/useSingleRequestParameter}}
{{/withInterfaces}}

{{#description}}
/**
 * {{&description}}
 */
{{/description}}
{{^providedInRoot}}
@Injectable()
{{/providedInRoot}}
{{#providedInRoot}}
@Injectable({
  providedIn: 'root'
})
{{/providedInRoot}}
{{#withInterfaces}}
export class {{classname}} implements {{classname}}Interface {
{{/withInterfaces}}
{{^withInterfaces}}
export class {{classname}} {
{{/withInterfaces}}

    protected basePath = '{{{basePath}}}';
    public defaultHeaders = new {{#useHttpClient}}Http{{/useHttpClient}}Headers();
    public configuration = new Configuration();
{{#useHttpClient}}
    public encoder: HttpParameterCodec;
{{/useHttpClient}}
{{^useHttpClient}}
    public encoder: QueryEncoder;
{{/useHttpClient}}

    constructor(protected {{#useHttpClient}}httpClient: HttpClient{{/useHttpClient}}{{^useHttpClient}}http: Http{{/useHttpClient}}, @Optional()@Inject(BASE_PATH) basePath: string, @Optional() configuration: Configuration) {
        if (configuration) {
            this.configuration = configuration;
        }
        if (typeof this.configuration.basePath !== 'string') {
            if (typeof basePath !== 'string') {
                basePath = this.basePath;
            }
            this.configuration.basePath = basePath;
        }
{{#useHttpClient}}
        this.encoder = this.configuration.encoder || new CustomHttpParameterCodec();
{{/useHttpClient}}
{{^useHttpClient}}
        this.encoder = this.configuration.encoder || new CustomQueryEncoderHelper();
{{/useHttpClient}}
    }

{{#hasSomeFormParams}}
    /**
     * @param consumes string[] mime-types
     * @return true: consumes contains 'multipart/form-data', false: otherwise
     */
    private canConsumeForm(consumes: string[]): boolean {
        const form = 'multipart/form-data';
        for (const consume of consumes) {
            if (form === consume) {
                return true;
            }
        }
        return false;
    }
{{/hasSomeFormParams}}

{{^useHttpClient}}
{{! Before HttpClient implementation or method overloading we relied on 2 functions, 1 to return the straight body as json
    and another to get the full response.}}
{{#operation}}
    /**
     * {{&notes}}
     {{#summary}}
     * @summary {{&summary}}
     {{/summary}}
     {{^useSingleRequestParameter}}{{#allParams}}
     * @param {{paramName}} {{description}}{{/allParams}}{{/useSingleRequestParameter}}
     {{#useSingleRequestParameter}}{{#allParams.0}}
     * @param requestParameters
     {{/allParams.0}}{{/useSingleRequestParameter}}*/
    {{! if you change this method signature, also change the version below }}
    public {{nickname}}({{^useSingleRequestParameter}}{{#allParams}}{{paramName}}{{^required}}?{{/required}}: {{{dataType}}}{{#hasMore}}, {{/hasMore}}{{/allParams}}{{/useSingleRequestParameter}}{{#useSingleRequestParameter}}{{#allParams.0}}requestParameters: {{#prefixParameterInterfaces}}{{classname}}{{/prefixParameterInterfaces}}{{operationIdCamelCase}}RequestParams{{/allParams.0}}{{/useSingleRequestParameter}}{{^useHttpClient}}{{#hasParams}}, {{/hasParams}}extraHttpRequestParams?: RequestOptionsArgs{{/useHttpClient}}): Observable<{{#returnType}}{{{returnType}}}{{#isResponseTypeFile}}|undefined{{/isResponseTypeFile}}{{/returnType}}{{^returnType}}{}{{/returnType}}> {
        return this.{{nickname}}WithHttpInfo({{^useSingleRequestParameter}}{{#allParams}}{{paramName}}, {{/allParams}}{{/useSingleRequestParameter}}{{#useSingleRequestParameter}}{{#allParams.0}}requestParameters, {{/allParams.0}}{{/useSingleRequestParameter}}extraHttpRequestParams)
            .map((response: Response) => {
                if (response.status === 204) {
                    return undefined;
                } else {
{{^isResponseFile}}
                    return response.json() || {};
{{/isResponseFile}}
{{#isResponseFile}}
                    return response.blob();
{{/isResponseFile}}
                }
            });
    }

{{/operation}}
{{/useHttpClient}}

    private addToHttpParams(httpParams: HttpParams, value: any, key?: string): HttpParams {
        if (typeof value === "object") {
            {{#useHttpClient}}httpParams = {{/useHttpClient}}this.addToHttpParamsRecursive(httpParams, value);
        } else {
            {{#useHttpClient}}httpParams = {{/useHttpClient}}this.addToHttpParamsRecursive(httpParams, value, key);
        }
        return httpParams;
    }

    private addToHttpParamsRecursive(httpParams: HttpParams, value?: any, key?: string): HttpParams {
        if (value == null) {
            return httpParams;
        }

        if (typeof value === "object") {
            if (Array.isArray(value)) {
                (value as any[]).forEach( elem => httpParams = this.addToHttpParamsRecursive(httpParams, elem, key));
            } else if (value instanceof Date) {
                if (key != null) {
                    {{#useHttpClient}}httpParams = {{/useHttpClient}}httpParams.append(key,
                        (value as Date).toISOString(){{^isDateTime}}.substr(0, 10)){{/isDateTime}};
                } else {
                   throw Error("key may not be null if value is Date");
                }
            } else {
                Object.keys(value).forEach( k => {{#useHttpClient}}httpParams = {{/useHttpClient}}this.addToHttpParamsRecursive(
                    httpParams, value[k], key != null ? `${key}.${k}` : k));
            }
        } else if (key != null) {
            {{#useHttpClient}}httpParams = {{/useHttpClient}}httpParams.append(key, value);
        } else {
            throw Error("key may not be null if value is not object or array");
        }
        return httpParams;
    }

{{#operation}}
    /**
{{#summary}}
     * {{summary}}
{{/summary}}
{{#notes}}
     * {{notes}}
{{/notes}}
     {{^useSingleRequestParameter}}
     {{#allParams}}
     * @param {{paramName}} {{description}}
     {{/allParams}}
     {{/useSingleRequestParameter}}
     {{#useSingleRequestParameter}}
     {{#allParams.0}}
     * @param requestParameters
     {{/allParams.0}}
     {{/useSingleRequestParameter}}
     {{#useHttpClient}}
     * @param observe set whether or not to return the data Observable as the body, response or events. defaults to returning the body.
     * @param reportProgress flag to report request and response progress.
     {{/useHttpClient}}
     */
    {{#useHttpClient}}
    public {{nickname}}({{^useSingleRequestParameter}}{{#allParams}}{{paramName}}{{^required}}?{{/required}}: {{{dataType}}}, {{/allParams}}{{/useSingleRequestParameter}}{{#useSingleRequestParameter}}{{#allParams.0}}requestParameters: {{#prefixParameterInterfaces}}{{classname}}{{/prefixParameterInterfaces}}{{operationIdCamelCase}}RequestParams, {{/allParams.0}}{{/useSingleRequestParameter}}observe?: 'body', reportProgress?: boolean, options?: {httpHeaderAccept?: {{#produces}}'{{mediaType}}'{{#hasMore}} | {{/hasMore}}{{/produces}}{{^produces}}undefined{{/produces}}}): Observable<{{#returnType}}{{{returnType}}}{{#isResponseTypeFile}}|undefined{{/isResponseTypeFile}}{{/returnType}}{{^returnType}}any{{/returnType}}>;
    public {{nickname}}({{^useSingleRequestParameter}}{{#allParams}}{{paramName}}{{^required}}?{{/required}}: {{{dataType}}}, {{/allParams}}{{/useSingleRequestParameter}}{{#useSingleRequestParameter}}{{#allParams.0}}requestParameters: {{#prefixParameterInterfaces}}{{classname}}{{/prefixParameterInterfaces}}{{operationIdCamelCase}}RequestParams, {{/allParams.0}}{{/useSingleRequestParameter}}observe?: 'response', reportProgress?: boolean, options?: {httpHeaderAccept?: {{#produces}}'{{mediaType}}'{{#hasMore}} | {{/hasMore}}{{/produces}}{{^produces}}undefined{{/produces}}}): Observable<HttpResponse<{{#returnType}}{{{returnType}}}{{#isResponseTypeFile}}|undefined{{/isResponseTypeFile}}{{/returnType}}{{^returnType}}any{{/returnType}}>>;
    public {{nickname}}({{^useSingleRequestParameter}}{{#allParams}}{{paramName}}{{^required}}?{{/required}}: {{{dataType}}}, {{/allParams}}{{/useSingleRequestParameter}}{{#useSingleRequestParameter}}{{#allParams.0}}requestParameters: {{#prefixParameterInterfaces}}{{classname}}{{/prefixParameterInterfaces}}{{operationIdCamelCase}}RequestParams, {{/allParams.0}}{{/useSingleRequestParameter}}observe?: 'events', reportProgress?: boolean, options?: {httpHeaderAccept?: {{#produces}}'{{mediaType}}'{{#hasMore}} | {{/hasMore}}{{/produces}}{{^produces}}undefined{{/produces}}}): Observable<HttpEvent<{{#returnType}}{{{returnType}}}{{#isResponseTypeFile}}|undefined{{/isResponseTypeFile}}{{/returnType}}{{^returnType}}any{{/returnType}}>>;
    public {{nickname}}({{^useSingleRequestParameter}}{{#allParams}}{{paramName}}{{^required}}?{{/required}}: {{{dataType}}}, {{/allParams}}{{/useSingleRequestParameter}}{{#useSingleRequestParameter}}{{#allParams.0}}requestParameters: {{#prefixParameterInterfaces}}{{classname}}{{/prefixParameterInterfaces}}{{operationIdCamelCase}}RequestParams, {{/allParams.0}}{{/useSingleRequestParameter}}observe: any = 'body', reportProgress: boolean = false, options?: {httpHeaderAccept?: {{#produces}}'{{mediaType}}'{{#hasMore}} | {{/hasMore}}{{/produces}}{{^produces}}undefined{{/produces}}}): Observable<any> {
    {{/useHttpClient}}
    {{^useHttpClient}}
    public {{nickname}}WithHttpInfo({{^useSingleRequestParameter}}{{#allParams}}{{paramName}}{{^required}}?{{/required}}: {{{dataType}}}, {{/allParams}}{{/useSingleRequestParameter}}{{#useSingleRequestParameter}}{{#allParams.0}}requestParameters: {{#prefixParameterInterfaces}}{{classname}}{{/prefixParameterInterfaces}}{{operationIdCamelCase}}RequestParams, {{/allParams.0}}{{/useSingleRequestParameter}}extraHttpRequestParams?: RequestOptionsArgs, options?: {httpHeaderAccept?: {{#produces}}'{{mediaType}}'{{#hasMore}} | {{/hasMore}}{{/produces}}{{^produces}}undefined{{/produces}}}): Observable<Response> {
    {{/useHttpClient}}
{{#allParams}}
{{#useSingleRequestParameter}}
        const {{paramName}} = requestParameters.{{paramName}};
{{/useSingleRequestParameter}}
{{#required}}
        if ({{paramName}} === null || {{paramName}} === undefined) {
            throw new Error('Required parameter {{paramName}} was null or undefined when calling {{nickname}}.');
        }
{{/required}}
{{/allParams}}

{{#hasQueryParams}}
        {{#useHttpClient}}
        let queryParameters = new HttpParams({encoder: this.encoder});
        {{/useHttpClient}}
        {{^useHttpClient}}
        let queryParameters = new URLSearchParams('', this.encoder);
        {{/useHttpClient}}
{{#queryParams}}
        {{#isListContainer}}
        if ({{paramName}}) {
        {{#isCollectionFormatMulti}}
            {{paramName}}.forEach((element) => {
                {{#useHttpClient}}queryParameters = {{/useHttpClient}}this.addToHttpParams(queryParameters,
                  <any>element, '{{baseName}}');
            })
        {{/isCollectionFormatMulti}}
        {{^isCollectionFormatMulti}}
            {{#useHttpClient}}queryParameters = {{/useHttpClient}}this.addToHttpParams(queryParameters,
                {{paramName}}.join(COLLECTION_FORMATS['{{collectionFormat}}']), '{{baseName}}');
        {{/isCollectionFormatMulti}}
        }
        {{/isListContainer}}
        {{^isListContainer}}
        if ({{paramName}} !== undefined && {{paramName}} !== null) {
          {{#useHttpClient}}queryParameters = {{/useHttpClient}}this.addToHttpParams(queryParameters,
            <any>{{paramName}}, '{{baseName}}');
        }
        {{/isListContainer}}
{{/queryParams}}

{{/hasQueryParams}}
        let headers = {{#useHttpClient}}this.defaultHeaders;{{/useHttpClient}}{{^useHttpClient}}new Headers(this.defaultHeaders.toJSON()); // https://github.com/angular/angular/issues/6845{{/useHttpClient}}
{{#headerParams}}
        {{#isListContainer}}
        if ({{paramName}}) {
            {{#useHttpClient}}headers = {{/useHttpClient}}headers.set('{{baseName}}', {{paramName}}.join(COLLECTION_FORMATS['{{collectionFormat}}']));
        }
        {{/isListContainer}}
        {{^isListContainer}}
        if ({{paramName}} !== undefined && {{paramName}} !== null) {
            {{#useHttpClient}}headers = {{/useHttpClient}}headers.set('{{baseName}}', String({{paramName}}));
        }
        {{/isListContainer}}
{{/headerParams}}

{{#authMethods}}
        // authentication ({{name}}) required
{{#isApiKey}}
{{#isKeyInHeader}}
        if (this.configuration.apiKeys && this.configuration.apiKeys["{{keyParamName}}"]) {
            {{#useHttpClient}}headers = {{/useHttpClient}}headers.set('{{keyParamName}}', this.configuration.apiKeys["{{keyParamName}}"]);
        }

{{/isKeyInHeader}}
{{#isKeyInQuery}}
        if (this.configuration.apiKeys && this.configuration.apiKeys["{{keyParamName}}"]) {
            {{#useHttpClient}}queryParameters = {{/useHttpClient}}queryParameters.set('{{keyParamName}}', this.configuration.apiKeys["{{keyParamName}}"]);
        }

{{/isKeyInQuery}}
{{/isApiKey}}
{{#isBasic}}
    {{#isBasicBasic}}
        if (this.configuration.username || this.configuration.password) {
            {{#useHttpClient}}headers = {{/useHttpClient}}headers.set('Authorization', 'Basic ' + btoa(this.configuration.username + ':' + this.configuration.password));
        }
    {{/isBasicBasic}}
    {{#isBasicBearer}}
        if (this.configuration.accessToken) {
            const accessToken = typeof this.configuration.accessToken === 'function'
                ? this.configuration.accessToken()
                : this.configuration.accessToken;
            {{#useHttpClient}}headers = {{/useHttpClient}}headers.set('Authorization', 'Bearer ' + accessToken);
        }
    {{/isBasicBearer}}
{{/isBasic}}
{{#isOAuth}}
        if (this.configuration.accessToken) {
            const accessToken = typeof this.configuration.accessToken === 'function'
                ? this.configuration.accessToken()
                : this.configuration.accessToken;
            {{#useHttpClient}}headers = {{/useHttpClient}}headers.set('Authorization', 'Bearer ' + accessToken);
        }

{{/isOAuth}}
{{/authMethods}}
        let httpHeaderAcceptSelected: string | undefined = options && options.httpHeaderAccept;
        if (httpHeaderAcceptSelected === undefined) {
            // to determine the Accept header
            const httpHeaderAccepts: string[] = [
                {{#produces}}
                '{{{mediaType}}}'{{#hasMore}},{{/hasMore}}
                {{/produces}}
            ];
            httpHeaderAcceptSelected = this.configuration.selectHeaderAccept(httpHeaderAccepts);
        }
        if (httpHeaderAcceptSelected !== undefined) {
{{^useHttpClient}}
            headers.set('Accept', httpHeaderAcceptSelected);
{{/useHttpClient}}
{{#useHttpClient}}
            headers = headers.set('Accept', httpHeaderAcceptSelected);
{{/useHttpClient}}
        }

{{#bodyParam}}
{{- duplicated below, don't forget to change}}
        // to determine the Content-Type header
        const consumes: string[] = [
            {{#consumes}}
            '{{{mediaType}}}'{{#hasMore}},{{/hasMore}}
            {{/consumes}}
        ];
{{/bodyParam}}
{{#hasFormParams}}
{{^bodyParam}}
        // to determine the Content-Type header
        const consumes: string[] = [
            {{#consumes}}
            '{{{mediaType}}}'{{#hasMore}},{{/hasMore}}
            {{/consumes}}
        ];
{{/bodyParam}}
{{/hasFormParams}}
{{#bodyParam}}
        const httpContentTypeSelected: string | undefined = this.configuration.selectHeaderContentType(consumes);
        if (httpContentTypeSelected !== undefined) {
{{^useHttpClient}}
            headers.set('Content-Type', httpContentTypeSelected);
{{/useHttpClient}}
{{#useHttpClient}}
            headers = headers.set('Content-Type', httpContentTypeSelected);
{{/useHttpClient}}
        }
{{/bodyParam}}

{{#hasFormParams}}
        const canConsumeForm = this.canConsumeForm(consumes);

        let formParams: { append(param: string, value: any): any; };
        let useForm = false;
        let convertFormParamsToString = false;
{{#formParams}}
{{#isFile}}
        // use FormData to transmit files using content-type "multipart/form-data"
        // see https://stackoverflow.com/questions/4007969/application-x-www-form-urlencoded-or-multipart-form-data
        useForm = canConsumeForm;
{{/isFile}}
{{/formParams}}
        if (useForm) {
            formParams = new FormData();
        } else {
{{#useHttpClient}}
            formParams = new HttpParams({encoder: this.encoder});
{{/useHttpClient}}
{{^useHttpClient}}
            // TODO: this fails if a parameter is a file, the api can't consume "multipart/form-data" and a blob is passed.
            convertFormParamsToString = true;
            formParams = new URLSearchParams('', this.encoder);
            // set the content-type explicitly to avoid having it set to 'text/plain'
            headers.set('Content-Type', 'application/x-www-form-urlencoded;charset=UTF-8');
{{/useHttpClient}}
        }

{{#formParams}}
        {{#isListContainer}}
        if ({{paramName}}) {
        {{#isCollectionFormatMulti}}
            {{paramName}}.forEach((element) => {
                {{#useHttpClient}}formParams = {{/useHttpClient}}formParams.append('{{baseName}}', <any>element){{#useHttpClient}} as any || formParams{{/useHttpClient}};
            })
        {{/isCollectionFormatMulti}}
        {{^isCollectionFormatMulti}}
            if (useForm) {
                {{paramName}}.forEach((element) => {
                    {{#useHttpClient}}formParams = {{/useHttpClient}}formParams.append('{{baseName}}', <any>element){{#useHttpClient}} as any || formParams{{/useHttpClient}};
            })
            } else {
                {{#useHttpClient}}formParams = {{/useHttpClient}}formParams.append('{{baseName}}', {{paramName}}.join(COLLECTION_FORMATS['{{collectionFormat}}'])){{#useHttpClient}} as any || formParams{{/useHttpClient}};
            }
        {{/isCollectionFormatMulti}}
        }
        {{/isListContainer}}
        {{^isListContainer}}
        if ({{paramName}} !== undefined) {
            {{#useHttpClient}}formParams = {{/useHttpClient}}formParams.append('{{baseName}}', {{^isModel}}<any>{{paramName}}{{/isModel}}{{#isModel}}useForm ? new Blob([JSON.stringify({{paramName}})], {type: 'application/json'}) : <any>{{paramName}}{{/isModel}}){{#useHttpClient}} as any || formParams{{/useHttpClient}};
        }
        {{/isListContainer}}
{{/formParams}}

{{/hasFormParams}}
{{#useHttpClient}}
    {{^isResponseFile}}
        let responseType: 'text' | 'json' = 'json';
        if(httpHeaderAcceptSelected && httpHeaderAcceptSelected.startsWith('text')) {
            responseType = 'text';
        }

    {{/isResponseFile}}
        return this.httpClient.{{httpMethod}}{{^isResponseFile}}<{{#returnType}}{{{returnType}}}{{#isResponseTypeFile}}|undefined{{/isResponseTypeFile}}{{/returnType}}{{^returnType}}any{{/returnType}}>{{/isResponseFile}}(`${this.configuration.basePath}{{{path}}}`,{{#isBodyAllowed}}
            {{#bodyParam}}{{paramName}}{{/bodyParam}}{{^bodyParam}}{{#hasFormParams}}convertFormParamsToString ? formParams.toString() : formParams{{/hasFormParams}}{{^hasFormParams}}null{{/hasFormParams}}{{/bodyParam}},{{/isBodyAllowed}}
            {
    {{#hasQueryParams}}
                params: queryParameters,
    {{/hasQueryParams}}
    {{#isResponseFile}}
                responseType: "blob",
    {{/isResponseFile}}
    {{^isResponseFile}}
                responseType: <any>responseType,
    {{/isResponseFile}}
                withCredentials: this.configuration.withCredentials,
                headers: headers,
                observe: observe,
                reportProgress: reportProgress
            }
        );
{{/useHttpClient}}
{{^useHttpClient}}
        let requestOptions: RequestOptionsArgs = new RequestOptions({
            method: {{httpMethod}},
            headers: headers,
{{#bodyParam}}
            body: {{paramName}} == null ? '' : JSON.stringify({{paramName}}), // https://github.com/angular/angular/issues/10612
{{/bodyParam}}
{{#hasFormParams}}
            body: convertFormParamsToString ? formParams.toString() : formParams,
{{/hasFormParams}}
{{#isResponseFile}}
            responseType: ResponseContentType.Blob,
{{/isResponseFile}}
{{^isResponseFile}}
            responseType: httpHeaderAcceptSelected && httpHeaderAcceptSelected.startsWith('text') ? ResponseContentType.Text : ResponseContentType.Json,
{{/isResponseFile}}
{{#hasQueryParams}}
            search: queryParameters,
{{/hasQueryParams}}
            withCredentials:this.configuration.withCredentials
        });
        // issues#4037
        if (extraHttpRequestParams) {
            requestOptions = (<any>Object).assign(requestOptions, extraHttpRequestParams);
        }

        return this.http.request(`${this.configuration.basePath}{{{path}}}`, requestOptions);
{{/useHttpClient}}
    }

{{/operation}}}
{{/operations}}
